package cn.sinjet.communication.bluetooth;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;

public class LeBluetoothService extends Service{
	private final static String tag = "BLE";
	private Handler mHandler = null;
//	private boolean mScanning = false;
	private boolean mHaveTlDevice = false;
	private static final long BT_SCAN_PERIOD = 15000;
	private static final int BT_CONNECT_TIMEOUT = 30000;
	//private boolean mIsConnectManually = false;//
	private BluetoothManager mBluetoothManager;
	private BluetoothAdapter mBluetoothAdapter;
	private BluetoothGatt mBluetoothGatt;
	private BluetoothDevice mBluetoothDevice;
	
	private static BluetoothGattCharacteristic target_chara = null;
	private int mConnectionState = BTState.DISCONNECTED;
	private boolean mIsConnecttingPeriod = false;
	//public final static String DEFAULT_DEVICE_ADDR = "00:18:66:36:00:DA";
	
	//toure
	public final static String TOURE_CHARACTERISTIC_NOTIFY = "0000ff01-0000-1000-8000-00805f9b34fb";
	public final static String TOURE_CHARACTERISTIC_WRITE =   "0000ff02-0000-1000-8000-00805f9b34fb";
//	public final static String DEFAULT_SERVICE_UUID = "0000ff00-0000-1000-8000-00805f9b34fb";
	                                                           
	//HC-08
	//����4.0��UUID,����0000ffe1-0000-1000-8000-00805f9b34fb�ǹ��ݻ����Ϣ�Ƽ����޹�˾08����ģ���UUID
	public static String HC08_SERVICE_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb";
	
//	public final static String DEFAULT_SERVICE_UUID = "0000ffe1-0000-1000-8000-00805f9b34fb";
	
	//0000ffe1-0000-1000-8000-00805f9b34fb
	public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID
			.fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT);

	public interface BleServiceCallback{
		void onBTStateChange(int state);
		void onReceived(byte[] message,int len); 
	}
	
	private BleServiceCallback mBleServiceCallback = null;
	
	public void setBleServiceCallback(BleServiceCallback bleServiceCallback){
		mBleServiceCallback = bleServiceCallback;
	}
	
	public boolean isInConnecttingPeriod(){
		return mIsConnecttingPeriod;
	}
	public void sendMessage(byte[] message){
		   if(!isBTConnected())
			   return;
		   if (mBluetoothGatt == null) {
				Log.d(tag, "send message but BluetoothGatt == null");
				return;
			}

			/*BluetoothGattService gattService = mBluetoothGatt.getService(UUID.fromString(DEFAULT_SERVICE_UUID));
			if (gattService == null) {
				Log.d(tag, "send message but BluetoothGattService == null");
				return;
			}
			// enableBattNoti(iDevice);
//			BluetoothGattCharacteristic target_chara = null;
			target_chara = gattService.getCharacteristic(UUID.fromString(DEFAULT_CHARACTERISTIC_WRITE));*/

			if (target_chara == null) {
				Log.d(tag, "send message but target_chara == null");
				return;
			}

			boolean status = false;
			int storedLevel = target_chara.getWriteType();
			Log.d(tag, "send message storedLevel ="+storedLevel);
			// alertLevel
			// .setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
			//System.out.println("setToMcu send!");
			byte []szMsg = new byte[message.length];
			System.arraycopy(message, 0, szMsg, 0, message.length);
			target_chara.setValue(szMsg);
			
//			m_bIsSendToMCUing = true;
			status = mBluetoothGatt.writeCharacteristic(target_chara);
			Log.d(tag, "send message write status:"+status);
	}
	// Implements callback methods for GATT events that the app cares about. For
	// gzxj,
	// connection change and services discovered.
	private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
		@Override
		public void onConnectionStateChange(BluetoothGatt gatt, int status,
				int newState) {
			Log.i(tag, "onConnectionStateChange: "+status+"->"+newState);
			if (newState == BluetoothProfile.STATE_CONNECTED) {
				Log.i(tag, "Connected to GATT server.");
			   if(mBluetoothGatt.discoverServices())
			   Log.i(tag, "Attempting to start service discovery");
			} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
				onBTStateChange(BTState.DISCONNECTED);
				if(mIsConnecttingPeriod){
					try{
						Thread.sleep(1000);
					}catch(Exception e){
						e.printStackTrace();
					}
					connect(mBluetoothDevice);
				}
			}
		}

		
		/*private void tryDelayReconnect(){
			try {
				Log.d(tag, "tryDelayReconnect");
				closeBTGatt();
				Thread.sleep(2000);
				//if(mIsConnectManually){
//					   mIsConnectManually = false;
					if(mIsConnecttingPeriod)
						return;
					scanThenConnect();
			   //}
			} catch (Exception e) {
				// TODO: handle exception
			}
		}*/
		@Override
		public void onServicesDiscovered(BluetoothGatt gatt, int status) {
			Log.i(tag, "onServicesDiscovered: "+status);
			if(status != BluetoothGatt.GATT_SUCCESS){
				/*mBluetoothAdapter.disable();
				Timer single_timer = new Timer();
				single_timer.schedule(new TimerTask(){
					@Override
					public void run() {
						// TODO Auto-generated method stub
						mBluetoothAdapter.enable();
					}
				}, 1000);*/
				
				if(mIsConnecttingPeriod){
					Timer second_timer = new Timer();
					second_timer.schedule(new TimerTask(){
						@Override
						public void run() {
							// TODO Auto-generated method stub
							initialize();
							connect(mBluetoothDevice);
						}
					}, 2000);
				}
			}
			
			if (status == BluetoothGatt.GATT_SUCCESS) {
				displayGattServices(getSupportedGattServices());
				onBTStateChange(BTState.CONNECTED);
				
			} else {
				Log.w(tag, "onServicesDiscovered received: " + status);
				try{
					Thread.sleep(1000);
				}catch(InterruptedException e){
					e.printStackTrace();
				}
				mBluetoothGatt.discoverServices();
			}
		}

		@Override
		public void onCharacteristicRead(BluetoothGatt gatt,
				BluetoothGattCharacteristic characteristic, int status) {
			Log.i(tag, "onCharacteristicRead: "+status);
			if (status == BluetoothGatt.GATT_SUCCESS) {
				onRecvCharacteristic(characteristic);
			}
		}

		@Override
		public void onDescriptorWrite(BluetoothGatt gatt,
				BluetoothGattDescriptor descriptor, int status) {
			   Log.i(tag, "onDescriptorWrite: "+status);
		}

		@Override
		public void onCharacteristicChanged(BluetoothGatt gatt,
				BluetoothGattCharacteristic characteristic) {
			Log.i(tag, "onCharacteristicChanged from: ");
			onRecvCharacteristic(characteristic);
//			if (characteristic.getValue() != null) {

				// System.out.println(characteristic.getStringValue(0));
//			}
			// System.out.println("--------onCharacteristicChanged-----");
		}

		@Override
		public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
			System.out.println("rssi = " + rssi);
		}

		public void onCharacteristicWrite(BluetoothGatt gatt,
			BluetoothGattCharacteristic characteristic, int status) {
			Log.i(tag, "onCharacteristicWrite: "+status);		
			//sendToMcu();
		};
	};

	
	@SuppressLint("InlinedApi") private void onRecvCharacteristic(final BluetoothGattCharacteristic characteristic) {
		if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
			int flag = characteristic.getProperties();
			int format = -1;
			if ((flag & 0x01) != 0) {
				format = BluetoothGattCharacteristic.FORMAT_UINT16;
				Log.d(tag, "Heart rate format UINT16.");
			} else {
				format = BluetoothGattCharacteristic.FORMAT_UINT8;
				Log.d(tag, "Heart rate format UINT8.");
			}
			final int heartRate = characteristic.getIntValue(format, 1);
			System.out.println("Received heart rate: %d" + heartRate);
			Log.d(tag, String.format("Received heart rate: %d", heartRate));
		} else {
			// For all other profiles, writes the data formatted in HEX.
			final byte[] data = characteristic.getValue();
			if (data != null && data.length > 0) {
//				final StringBuilder stringBuilder = new StringBuilder(data.length);
//				for (byte byteChar : data)
//					stringBuilder.append(String.format("%02X ", byteChar));
//				Log.i(tag,"bt recvMessage: "+ stringBuilder.toString());
				if(mBleServiceCallback != null)
					mBleServiceCallback.onReceived(data,data.length);
				
//				final StringBuilder stringBuilder = new StringBuilder(
//						data.length);
//				for (byte byteChar : data)
//					stringBuilder.append(String.format("%02X ", byteChar));
				
//				Log.(tag,"recv:"+stringBuilder.);
			}
		}
	}

	public class LocalBinder extends Binder {
		public LeBluetoothService getService() {
			return LeBluetoothService.this;
		}
	}

	@Override
	public IBinder onBind(Intent intent) {
		return mBinder;
	}

	@Override
	public boolean onUnbind(Intent intent) {
		// After using a given device, you should make sure that
		// BluetoothGatt.close() is called
		// such that resources are cleaned up properly. In this particular
		// gzxj, close() is
		// invoked when the UI is disconnected from the Service.
		Log.i(tag, "onUnbind close.");
		scanLeDevice(false);
		disconnectBTGatt();
		closeBTGatt();
		return super.onUnbind(intent);
	}

	private final IBinder mBinder = new LocalBinder();

	

	/**
	 * Initializes a reference to the local Bluetooth adapter.
	 * 
	 * @return Return true if the initialization is successful.
	 */
	@SuppressLint("InlinedApi") private boolean initialize() {
		// For API level 18 and above, get a reference to BluetoothAdapter
		if (mBluetoothManager == null) 
			mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
		if (mBluetoothManager == null)   return false;
		
		if(mBluetoothAdapter == null)
		mBluetoothAdapter = mBluetoothManager.getAdapter();
		if(mBluetoothAdapter == null) return false;
		
		if(mHandler == null)
			mHandler = new Handler();
		if(mHandler == null) return false;
		
		return true;
	}

	/**
	 * Connects to the GATT server hosted on the Bluetooth LE device.
	 * 
	 * @param device.getAddress()
	 *            The device address of the destination device.
	 * 
	 * @return Return true if the connection is initiated successfully. The
	 *         connection result is reported asynchronously through the
	 *         {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
	 *         callback.
	 */
	
	
	
	
	/*
	 * isSearchResult
	 * */
	public boolean connect(final BluetoothDevice device) {
		if (mBluetoothAdapter == null || device == null) {
			Log.w(tag,"BluetoothAdapter not initialized or unspecified address.");
			return false;
		}

//		closeBTGatt();

		// We want to directly connect to the device, so we are setting the
		// autoConnect
		// parameter to false.
		closeBTGatt();//must call this to ensure the resource is release
		
		Log.d(tag, "Trying a connection with BT addr:"+device.getAddress());
		mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
		if(mBluetoothGatt == null){
			Log.e(tag, "get BluetoothGatt is null!");
			return false;
		}
		
		onBTStateChange(BTState.CONNECTING);
		return true;
	}

	/**
	 * Disconnects an existing connection or cancel a pending connection. The
	 * disconnection result is reported asynchronously through the
	 * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
	 * callback.
	 */
	private void disconnectBTGatt() {
		if (mBluetoothAdapter == null || mBluetoothGatt == null) {
			Log.w(tag, "BluetoothAdapter not initialized");
			return;
		}
		mBluetoothGatt.disconnect();
	}

	/**
	 * After using a given BLE device, the app must call this method to ensure
	 * resources are released properly.
	 */
	private void closeBTGatt() {
		if (mBluetoothGatt == null) {
			return;
		}
		Log.e(tag, "mBluetoothGatt.close();");
		mBluetoothGatt.close();
		mBluetoothGatt = null;
	}

//	private void wirteCharacteristic(BluetoothGattCharacteristic characteristic) {
//
//		if (mBluetoothAdapter == null || mBluetoothGatt == null) {
//			Log.w(tag, "BluetoothAdapter not initialized");
//			return;
//		}
//		mBluetoothGatt.writeCharacteristic(characteristic);
//	}

	final BlockingQueue<Node> m_bleMsgQueue = new ArrayBlockingQueue<Node>(128);
//	public boolean m_bIsSendToMCUing = false;
	
	class Node {
		public byte[] msgBuf = new byte[32];
		public int msgLength = 0;

		public Node() {
			msgLength = 0;
		}
	}

	public boolean isBTConnected(){
		return (mConnectionState==BTState.CONNECTED)?true:false;
	}
	/*public void setToMcu(byte[] p, int len) {
         
        if(!isBTConnected()){
        	Log.d(tag,"setToMcu but not connected!");	
        	return ;
        }
        	
		byte[] szMsg = new byte[len + 5];
		szMsg[0] = (byte) 0xFF;
		szMsg[1] = (byte) 0x55;
		szMsg[2] = (byte) (len + 1);
		szMsg[3] = (byte) 0x03;
		System.arraycopy(p, 0, szMsg, 4, len);

		byte sum = 0;
		int s = 0;
		int i = 0;
		for (i = 2; i < len + 4; i++) {
			s += (szMsg[i] & 0xFF);
		}
		sum = (byte) (s & 0xFF);
		szMsg[len + 4] = sum;

		//Log.d(tag,"setToMcu"); 
		Node n = new Node();
		n.msgLength = len + 5;
		System.arraycopy(szMsg, 0, n.msgBuf, 0, n.msgLength);
		m_bleMsgQueue.offer(n);
		Log.d(tag,"m_bleMsgQueue.offer after len"+n.msgLength); 
		//if (!m_bIsSendToMCUing)
		{
			sendToMcu();
		}
	}*/

	/*public void sendToMcu() {
		
		Node n = m_bleMsgQueue.poll();
		if (n == null)
		{
			Log.d(tag, "sendToMcu node is null");
			return ;
		}
		
		//start
		if (mBluetoothGatt == null) {
			System.out.println("setToMcu mBluetoothGatt == null");
			return;
		}

		BluetoothGattService gzxjService = mBluetoothGatt.getService(UUID.fromString(DEFAULT_SERVICE_UUID));
		if (gzxjService == null) {
			System.out.println("setToMcu gzxjService");
			return;
		}
		// enableBattNoti(iDevice);
		BluetoothGattCharacteristic alertLevel = null;
		alertLevel = gzxjService.getCharacteristic(UUID.fromString(DEFAULT_CHARACTERISTIC_WRITE));

		if (alertLevel == null) {
			System.out.println("setToMcu alertLevel");
			return;
		}

		boolean status = false;
		int storedLevel = alertLevel.getWriteType();
		System.out.println("setToMcu storedLevel = " + storedLevel);

		// alertLevel
		// .setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
		System.out.println("setToMcu send!");
		byte []szMsg = new byte[n.msgLength];
		System.arraycopy(n.msgBuf, 0, szMsg, 0, n.msgLength);
		alertLevel.setValue(szMsg);
		
//		m_bIsSendToMCUing = true;
		status = mBluetoothGatt.writeCharacteristic(alertLevel);
		System.out.println("setToMcu status = " + status);

		// EnvCenter.showToast("setToMcu ans = " + status);

	}*/

	/**
	 * Request a read on a given {@code BluetoothGattCharacteristic}. The read
	 * result is reported asynchronously through the
	 * {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)}
	 * callback.
	 * 
	 * @param characteristic
	 *            The characteristic to read from.
	 */
	public void readCharacteristic(BluetoothGattCharacteristic characteristic) {
		if (mBluetoothAdapter == null || mBluetoothGatt == null) {
			Log.w(tag, "BluetoothAdapter not initialized");
			return;
		}
		mBluetoothGatt.readCharacteristic(characteristic);
	}

	/**
	 * Enables or disables notification on a give characteristic.
	 * 
	 * @param characteristic
	 *            Characteristic to act on.
	 * @param enabled
	 *            If true, enable notification. False otherwise.
	 */
	@SuppressLint("InlinedApi") public void setCharacteristicNotification(
			BluetoothGattCharacteristic characteristic, boolean enabled) {
		if (mBluetoothAdapter == null || mBluetoothGatt == null) {
			Log.w(tag, "BluetoothAdapter not initialized");
			return;
		}
		mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
		BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID
				.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
		if (descriptor != null) {
			System.out.println("write descriptor");
			descriptor
					.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
			mBluetoothGatt.writeDescriptor(descriptor);
		}
		/*
		 * // This is specific to Heart Rate Measurement. if
		 * (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) {
		 * System
		 * .out.println("characteristic.getUuid() == "+characteristic.getUuid
		 * ()+", "); BluetoothGattDescriptor descriptor =
		 * characteristic.getDescriptor
		 * (UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
		 * descriptor
		 * .setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
		 * mBluetoothGatt.writeDescriptor(descriptor); }
		 */
	}

	/**
	 * Retrieves a list of supported GATT services on the connected device. This
	 * should be invoked only after {@code BluetoothGatt#discoverServices()}
	 * completes successfully.
	 * 
	 * @return A {@code List} of supported services.
	 */
	public List<BluetoothGattService> getSupportedGattServices() {
		if (mBluetoothGatt == null)
			return null;

		return mBluetoothGatt.getServices();
	}

	/**
	 * Read the RSSI for a connected remote device.
	 * */
	public boolean getRssiVal() {
		if (mBluetoothGatt == null)
			return false;

		return mBluetoothGatt.readRemoteRssi();
	}
	
	
//	public void connectDevice(String name){
//		if(!initialize())
//			return;
//		Log.i(tag, "connectDevice");
//	   disconnectBTGatt();
//	   closeBTGatt();
//	   scanLeDevice(false);
//	   scanLeDevice(true);
//	}
	
	public void requestConnection(){
		Log.i(tag, "requestConnection manually");
		if(mIsConnecttingPeriod)
			return;
		startConnectTimeoutHandler();
		scanThenConnect();
	}
	
	private void startConnectTimeoutHandler(){
		mIsConnecttingPeriod = true;
		if(mHandler == null)
			mHandler = new Handler();
//		mHandler.removeCallbacks(mConnectTimeoutRunnable);
		mHandler.postDelayed(mConnectTimeoutRunnable, BT_CONNECT_TIMEOUT);
	}
	
	
	Runnable mConnectTimeoutRunnable = new Runnable() {
		@Override
		public void run() {
			// TODO Auto-generated method stub
           	  mIsConnecttingPeriod = false;
           	  Log.d(tag, "Connect BT timeout!!!");
           	  //stop BT LeService
           	  if(!isBTConnected()){
           	      onBTStateChange(BTState.DISCONNECTED);
           	      BluetoothModel.getInstance().clearBTMode();
           	  }
		}
	};  
	
	
	
	private void scanThenConnect(){
		Log.i(tag, "scanThenConnect");
		if(!initialize())
			return;

		 scanLeDevice(false);
		 scanLeDevice(true);
		 
	}
	
	
	public void disconnectDevice(){
		Log.i(tag, "disconnectDevice");
		scanLeDevice(false);
//		mIsConnectManually = false;
		disconnectBTGatt();
	}
	
	private void scanLeDevice(final boolean enable) {
		Log.i(tag, "scanLeDevice = " + enable);
		if (mBluetoothAdapter == null) 
			return;

		if (enable) {
			// Stops scanning after a pre-defined scan period.
			mHandler.removeCallbacks(mEndScanRunnable);
			mHandler.postDelayed(mEndScanRunnable, BT_SCAN_PERIOD);
			//clearBleDeviceList();
			mHaveTlDevice = false;
//			mScanning = true;
            onBTStateChange(BTState.SCANING);
            //UUID[] uuids = new UUID[]{UUID.fromString(DEFAULT_SERVICE_UUID)};
			//mBluetoothAdapter.startLeScan(uuids,mBLEScanCallback);
            mBluetoothAdapter.startLeScan(mBLEScanCallback);
		} else {
//			mScanning = false;
			mHandler.removeCallbacks(mEndScanRunnable);
			mBluetoothAdapter.stopLeScan(mBLEScanCallback);
			
		}
	}
	
	Runnable mEndScanRunnable = new Runnable() {
		@Override
		public void run() {
			// TODO Auto-generated method stub
//			mScanning = false;
			mBluetoothAdapter.stopLeScan(mBLEScanCallback);
			if(mConnectionState == BTState.SCANING && !mHaveTlDevice)
		    onBTStateChange(BTState.NOT_FOUND);
			if(mIsConnecttingPeriod)
				scanLeDevice(true);
		}
	};
	private BluetoothAdapter.LeScanCallback mBLEScanCallback = new BluetoothAdapter.LeScanCallback() {

		@Override
		public void onLeScan(final BluetoothDevice device, final int rssi,final byte[] scanRecord) {
			new Thread() {
				public void run() {
					try {
//						Log.i(tag, "device = " + device.toString());
    //						Log.i(tag, "rssi = " + rssi);
    //					Log.i(tag, "scanRecordlength = " + scanRecord.length);
	//					Log.i(tag, "device.name = " + device.getName());
	//					Log.i(tag, "device.address = " + device.getAddress());
//						Log.i(tag,"device.BondState = " + device.getBondState());
//						Log.i(tag, "device.Type = " + device.getType());
                        String name = device.getName();
						String addr = device.getAddress();
						Log.i(tag, "device found name:" + name);
						Log.i(tag, "device found addr: = " + addr);

//						String strDeviceName = device.getName();
						/*if (name == null)
							name = mDeviceName;//
                         */
						if (      (name != null&& name.equals(BluetoothModel.BT_NAME1))
								|| (name != null&& name.equals(BluetoothModel.BT_NAME2))
								|| (addr != null && addr.equals("00:18:66:66:00:DA"))
							) {
							Log.i(tag, "sinjet device found!");
							mHaveTlDevice = true;
							scanLeDevice(false);//no need scan any more
							// sendOneBroadcast(EnvCenter.ACTION_BT_RESPONSE_STATUS,
							
							if (addr != null) {
								    mBluetoothDevice = device;
									connect(device);
						    } else {
									onBTStateChange(BTState.DISCONNECTED);
							}
						}
					} catch (Exception e) {
						Log.e("Exception when sendKeyDownUpSync", e.toString());
					}
				}
			}.start();
		}
		
	};
		
	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		Log.d(tag, "onDestroy");
		closeBTGatt();
		super.onDestroy();
	}
	
	@Override
	public void onLowMemory() {
		// TODO Auto-generated method stub
		super.onLowMemory();
	}

	private void onBTStateChange(int newState){
		if(mConnectionState == newState)
			return;
		Log.d(tag,"onBTStateChange:"+newState);
		mConnectionState = newState;
		if(mBleServiceCallback != null)
			mBleServiceCallback.onBTStateChange(newState);
		
		if(mConnectionState == BTState.CONNECTED){
			mIsConnecttingPeriod = false;
			mHandler.removeCallbacks(mConnectTimeoutRunnable);
		}
	}
	
	private void displayGattServices(List<BluetoothGattService> gattServices) {
		if (gattServices == null) {
			return;
		}
		for (BluetoothGattService gattService : gattServices) {
			List<BluetoothGattCharacteristic> gattCharacteristics = gattService.getCharacteristics();
			for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
				//toure
				if (gattCharacteristic.getUuid().toString().equals(TOURE_CHARACTERISTIC_NOTIFY)) {
					setCharacteristicNotification(gattCharacteristic, true);
				}
				
				if (gattCharacteristic.getUuid().toString().equals(TOURE_CHARACTERISTIC_WRITE)) {
					setCharacteristicNotification(gattCharacteristic, true);
					readCharacteristic(gattCharacteristic);
					target_chara = gattCharacteristic;
				}
				//HC-08
				if(gattCharacteristic.getUuid().toString().equals(HC08_SERVICE_UUID)){
					setCharacteristicNotification(gattCharacteristic, true);
					readCharacteristic(gattCharacteristic);
					target_chara = gattCharacteristic;
				}
				
			}
		}
	}
	
	/**
	 * This class includes a small subset of standard GATT attributes for demonstration purposes.
	 */
	private class SampleGattAttributes {
	    public static final  String HEART_RATE_MEASUREMENT = "0000C004-0000-1000-8000-00805f9b34fb";
	    public static final String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
	}	
}


